/*
 * Title:        CloudScheduler Toolkit
 * Description:  a Toolkit for Modeling and Simulation of Job Scheduling and Resource Provisioning in Cloud System
 * Licence:      GPL - http://www.gnu.org/copyleft/gpl.html
 * Author:       Fuhui Wu
 *
 * Copyright (c) 2013-2014, The National University of Defense Technology, China
 */

package org.nudt.jCloud.simulation;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.nudt.jCloud.infrastructure.Slot;
import org.nudt.jCloud.infrastructure.SlotType;
import org.nudt.jCloud.workload.Task;

public class RequestData {
	private List<Request> requestList;
	private int mode;
	private boolean sorted;		
	
	/**
	 * 
	 * @param requestList
	 * @param mode IntermediateData for different resource manager and job scheduler. 
	 * 			0: Reservation; 1: share state.
	 */
	public RequestData(){
		setRequestList(new ArrayList<Request>());
		setMode(0);
		setSorted(false);
	}
	
	public void reset(){
		requestList.clear();
		setSorted(false);
	}
	
	public void init(List<Request> requestList, int mode){
		reset();
		setRequestList(requestList);
		setMode(mode);
		setSorted(false);
	}
	
	public Map<SlotType, Integer> requestLoad(){
		Map<SlotType, Integer> requestLoad = new HashMap<SlotType, Integer>();
		for(int i=0; i<requestList.size(); ++i){
			Request request = requestList.get(i);
			for(int j=0; j<request.getUnAssignedTasks().size(); ++j){
				Task task = request.getUnAssignedTasks().get(j);
				SlotType slotType = task.getJob().getSlotType();
				if(requestLoad.containsKey(slotType)){
					requestLoad.put(slotType, requestLoad.get(slotType)+1);
				}else{
					requestLoad.put(slotType, new Integer(1));
				}
			}
		}
		return requestLoad;
	}

	public void sortByArrivalTime(){
		if(isSorted()==false){
			Collections.sort(requestList, new Request.SortByArrivalTime());
			setSorted(true);
		}
	}
	
	public void sortBySizeInc(){
		if(isSorted()==false){
			Collections.sort(requestList, new Request.SortBySizeInc());
			setSorted(true);
		}
	}
	
	public void sortBySizeDec(){
		if(isSorted()==false){
			Collections.sort(requestList, new Request.SortBySizeDec());
			setSorted(true);
		}
	}
	
	public void sortByScheduledInc(){
		if(isSorted()==false){
			Collections.sort(requestList, new Request.SortByScheduledInc());
			setSorted(true);
		}
	}
	
	public Task nextTask(Slot maxSlot){
		Task task = null;
		if(mode == 1){
			sortByArrivalTime();
			double legalTime = 0;
			for(int i=0; i<requestList.size(); ++i){
				legalTime = requestList.get(i).getJob().getArrivalTime();
				if(requestList.get(i).getUnAssignedTasks().size()<=0){
					if(i==requestList.size()-1){
						break;
					}else{
						legalTime = requestList.get(i+1).getJob().getArrivalTime();
						continue;
					}					
				}else{
					task = requestList.get(i).nextTask(maxSlot);
					if(task!=null){
						break;
					}else{
						if(requestList.get(i+1).getJob().getArrivalTime()<=legalTime){
							continue;
						}else{
							break;
						}
					}
				}
			}
		}
		return task;
	}
			
	public List<Request> getRequestList() {
		return requestList;
	}

	public void setRequestList(List<Request> requestList) {
		this.requestList = requestList;
	}

	public int getMode() {
		return mode;
	}

	public void setMode(int mode) {
		this.mode = mode;
	}
	
	public boolean isSorted(){
		return sorted;
	}
	
	public void setSorted(boolean sorted){
		this.sorted = sorted;
	}

}
